﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisualStateManager
{
    public class BaseVisualStateManager
    {
        // Private fields ------------------------------------------------------

        protected List<object> controls;
        protected BaseCondition enabledCondition;
        protected BaseCondition checkedCondition;
        protected BaseCondition visibleCondition;

        // Private methods -----------------------------------------------------

        private void ApplyCheckedToAll(bool value)
        {
            foreach (var control in controls)
                ControlOperatorManager.SetChecked(control, value);
        }

        private void ApplyEnabledToAll(bool value)
        {
            foreach (var control in controls)
                ControlOperatorManager.SetEnabled(control, value);
        }

        private void ApplyVisibleToAll(bool value)
        {
            foreach (var control in controls)
                ControlOperatorManager.SetVisible(control, value);
        }

        private void HandleCheckedConditionChanged(object sender, ValueChangedEventArgs e)
        {
            ApplyCheckedToAll(e.Value);
        }

        private void HandleEnabledConditionChanged(object sender, ValueChangedEventArgs e)
        {
            ApplyEnabledToAll(e.Value);
        }

        private void HandleVisibleConditionChanged(object sender, ValueChangedEventArgs e)
        {
            ApplyVisibleToAll(e.Value);
        }

        private void Initialize()
        {
            controls = new List<object>();
        }

        // Protected methods ---------------------------------------------------

        protected virtual void AddingControl(object control)
        {

        }

        protected virtual void RemovingControl(object control)
        {

        }

        // Public methods ------------------------------------------------------

        public BaseVisualStateManager()
        {
            Initialize();
        }

        public BaseVisualStateManager(params object[] controls)
        {
            Initialize();

            foreach (var control in controls)
            {
                AddControl(control);
            }
        }

        public BaseVisualStateManager(BaseCondition newEnabledCondition, params object[] controls)
        {
            Initialize();

            EnabledCondition = newEnabledCondition;

            foreach (var control in controls)
            {
                AddControl(control);
            }
        }

        public BaseVisualStateManager(BaseCondition newEnabledCondition,
            BaseCondition newCheckedCondition,
            params object[] controls)
        {
            Initialize();

            EnabledCondition = newEnabledCondition;
            CheckedCondition = newCheckedCondition;

            foreach (var control in controls)
            {
                AddControl(control);
            }
        }

        public BaseVisualStateManager(BaseCondition newEnabledCondition,
            BaseCondition newCheckedCondition,
            BaseCondition newVisibleCondition,
            params object[] controls)
        {
            Initialize();

            EnabledCondition = newEnabledCondition;
            CheckedCondition = newCheckedCondition;
            VisibleCondition = newVisibleCondition;

            foreach (var control in controls)
            {
                AddControl(control);
            }
        }

        public void AddControl(object control)
        {
            if (control == null)
                throw new ArgumentNullException("control");

            controls.Add(control);

            if (checkedCondition != null)
                ControlOperatorManager.SetChecked(control, checkedCondition.GetValue());
            if (enabledCondition != null)
                ControlOperatorManager.SetEnabled(control, enabledCondition.GetValue());
            if (visibleCondition != null)
                ControlOperatorManager.SetVisible(control, visibleCondition.GetValue());

            AddingControl(control);
        }

        public void RemoveControl(object control)
        {
            int index = controls.IndexOf(control);
            if (index > 0)
            {
                RemovingControl(control);

                controls.RemoveAt(index);
            }
        }

        // Public properties ---------------------------------------------------

        public BaseCondition CheckedCondition
        {
            get
            {
                return checkedCondition;
            }
            set
            {
                if (checkedCondition != null)
                    checkedCondition.ValueChanged -= HandleCheckedConditionChanged;

                checkedCondition = value;

                if (checkedCondition != null)
                {
                    checkedCondition.ValueChanged += HandleCheckedConditionChanged;

                    ApplyCheckedToAll(checkedCondition.GetValue());
                }
            }
        }

        public BaseCondition EnabledCondition
        {
            get
            {
                return enabledCondition;
            }
            set
            {
                if (enabledCondition != null)
                    enabledCondition.ValueChanged -= HandleEnabledConditionChanged;

                enabledCondition = value;

                if (enabledCondition != null)
                {
                    enabledCondition.ValueChanged += HandleEnabledConditionChanged;

                    ApplyEnabledToAll(enabledCondition.GetValue());
                }
            }
        }

        public BaseCondition VisibleCondition
        {
            get
            {
                return visibleCondition;
            }
            set
            {
                if (visibleCondition != null)
                    visibleCondition.ValueChanged -= HandleVisibleConditionChanged;

                visibleCondition = value;

                if (visibleCondition != null)
                {
                    visibleCondition.ValueChanged += HandleVisibleConditionChanged;

                    ApplyVisibleToAll(visibleCondition.GetValue());
                }
            }
        }
    }
}
